﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using Microsoft.Practices.Unity;
using JTLeigh.Commerce.Spencer.Core.Common;
using JTLeigh.Commerce.Spencer.Features.ProductImages.Business.Services;
using JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.Common;

// aliases for entities
using LocalizedProductImageE = JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities.LocalizedProductImage;
using LocalizedProductImageViewE = JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities.LocalizedProductImageView;
using LocalizedProductImageSizeE = JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities.LocalizedProductImageSize;
using ProductImageVariantE = JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities.ProductImageVariant;

// aliases for contracts
using GetProductImageSnapshotRequestC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImageSnapshot.GetProductImageSnapshotRequest;
using GetProductImageSnapshotResponseC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImageSnapshot.GetProductImageSnapshotResponse;
using ProductImageSnapshotC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImageSnapshot.ProductImageSnapshot;

namespace JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Commands.Runtime
{

	/// <summary>
	/// Command for getting a single image for a single product, view, and size combination.
	/// </summary>
	public class GetProductImageSnapshotCommand
	{

		#region Properties

		/// <summary>
		/// Gets or sets the product image metadata service to use to get product image metadata.
		/// </summary>
		/// <value>An <see cref="IProductImageMetadataService"/> implementation.</value>
		[Dependency]
		public IProductImageMetadataService ProductImageMetadataService { get; set; }

		/// <summary>
		/// Gets or sets the product image service to use to get product images.
		/// </summary>
		/// <value>An <see cref="IProductImageService"/> implementation.</value>
		[Dependency]
		public IProductImageService ProductImageService { get; set; }

		#endregion // Properties

		#region Methods

		/// <summary>
		/// Gets a single image for a single product, view, and size combination.
		/// </summary>
		/// <param name="request">The <see cref="GetProductImageSnapshotRequestC"/> request object.</param>
		/// <returns>The <see cref="GetProductImageSnapshotResponseC"/> response object.</returns>
		public GetProductImageSnapshotResponseC GetProductImageSnapshot(GetProductImageSnapshotRequestC request)
		{
			LocalizedProductImageSizeE size;
			LocalizedProductImageViewE view;
			Dictionary<Guid, LocalizedProductImageE> images;
			ProductImageVariantE variant;
			GetProductImageSnapshotResponseC response;

			Safety.AssertArgumentNotNull("request", request);

			size = ProductImageMetadataService.GetProductImageSizeByWellKnownSizeCode(request.TenantId, request.WellKnownSizeCode, request.CultureId);
			if (size == null)
			{
				// TODO: Log this condition.
				throw new FaultException<UnknownProductImageSizeFault>(new UnknownProductImageSizeFault
				{
					TenantId = request.TenantId,
					WellKnownSizeCode = request.WellKnownSizeCode
				}
				);
			}

			view = ProductImageMetadataService.GetProductImageViewByWellKnownViewCode(request.TenantId, request.WellKnownViewCode, request.CultureId);
			if (view == null)
			{
				// TODO: Log this condition.
				throw new FaultException<UnknownProductImageViewFault>(new UnknownProductImageViewFault
				{
					TenantId = request.TenantId,
					WellKnownViewCode = request.WellKnownViewCode
				}
				);
			}

			images = ProductImageService.GetProductImages(request.TenantId, request.ProductId.CatalogId, request.ProductId.ProductId, request.CultureId);

			// NOTE: images is keyed on ImageId, not ViewId, so we need to loop through all images
			// until we find one with the correct ViewId.
			foreach (LocalizedProductImageE image in images.Values)
			{
				if (image.ViewId.Equals(view.ViewId))
				{
					// NOTE: variants is keyed on SizeId, so we don't need to loop through all 
					// variants, and can just try to get the one we need instead.
					if (image.Variants.TryGetValue(size.SizeId, out variant))
					{
						response = new GetProductImageSnapshotResponseC
						{
							Snapshot = new ProductImageSnapshotC()
							{
								AlternativeText = image.AlternativeText,
								UsagePermissionText = image.UsagePermissionText,
								Width = size.Width,
								Height = size.Height,
								Path = variant.Path,
								OtherSizes = image.Variants.Count - 1,
								OtherImages = images.Count - 1
							}
						};
						return response;
					}
				}
			}

			response = new GetProductImageSnapshotResponseC
			{
				Snapshot = new ProductImageSnapshotC
				{
					AlternativeText = null, // FEAT: Return default alternative text for this tenant?
					UsagePermissionText = null, // FEAT: Return default usage permission text for this tenant?
					Width = size.Width,
					Height = size.Height,
					Path = size.MissingImagePath,
					OtherSizes = 0,
					OtherImages = images.Count
				}
			};
			return response;
		}

		#endregion // Methods

	}

}
